/************************************************************************
This file is part of java core libraries for the simpleRTJ virtual machine.

This file is covered by the GNU GPL with the following exception:
  As a special exception, the copyright holders of this library give you permission
  to link this library with independent modules to produce an executable, regardless
  of the license terms of these independent modules, and to copy and distribute the
  resulting executable under terms of your choice, provided that you also meet, for
  each linked independent module, the terms and conditions of the license of that
  module. An independent module is a module which is not derived from or based on
  this library. If you modify this library, you may extend this exception to your
  version of the library, but you are not obligated to do so. If you do not wish
  to do so, delete this exception statement from your version.


THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL RTJ COMPUTING BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Copyright (c) 2000-2002 RTJ Computing Pty. Ltd. All rights reserved.
***********************************************************************/
package javax.memory;

/**
 * The instances of a Flash class can access data in the flash memory loacted on
 * the target device. Native code routines provide erase/write alogorithms that are
 * common to most flash memory chips from AMD and other manufactures. Please verify
 * with the flash memory data sheets if the used algortithm is suitable for your
 * flash memory.
 * <p>
 *
 * In order to use this class in your application follow the following steps:<br>
 *    1. Locate the Flash.c in the source/javax/memory/native directory<br>
 *    2. Copy this file into your project's native code directory and
 *       make it part of the native code building process.
 */
public class Flash extends MemoryRegion
{
    /**
     * Creates a new memory region object.
     *
     * @param start starting address of a new memory region.
     * @param length length of a new memory region.
     * @exception InvalidMemoryRegionException is thrown when the requested region
     *      is invalid, i.e. overlaps with some other memory regions or there is no
     *      physical memory at specified location.
     */
    public Flash(int start, int length) throws InvalidMemoryRegionException
    {
        super(start, length);
    }

    /**
     * Writes a <code>byte</code> into memory at current offset. Method setOffset()
     * should be called prior calling this method to setup the offset pointer.<br>
     * Offset pointer will be modified by 1 if post-increment is enabled or -1 if
     * post-decrement is enabled.
     *
     * @param value  a byte value that will be written into memory. Only lower 8 bits are written.
     * @exception RegionAddressOutOfBoundsException is thrown when trying to access data out of bounds
     *      of this memory region.
     */
    public void writeByte(int value) throws RegionAddressOutOfBoundsException
    {
        if (regStart + memOffs < regStart || regStart + memOffs >= regEnd)
            throw new RegionAddressOutOfBoundsException();

        writeByte0(regStart + memOffs, value);
        if (postIncrement)
            memOffs++;
        else if (postDecrement)
            memOffs--;
    }

    /**
     * Writes a <code>short</code> into memory at current offset. Method setOffset()
     * should be called prior calling this method to setup the offset pointer.<br>
     * Offset pointer will be modified by 2 if post-increment is enabled or -2 if
     * post-decrement is enabled.
     *
     * @param value  a short value that will be written into memory. Only lower 16 bits are written.
     * @exception RegionAddressOutOfBoundsException is thrown when trying to access data out of bounds
     *      of this memory region.
     */
    public void writeShort(int value) throws RegionAddressOutOfBoundsException
    {
        if (regStart + memOffs < regStart || regStart + memOffs >= regEnd)
            throw new RegionAddressOutOfBoundsException();

        writeShort0(regStart + memOffs, value);
        if (postIncrement)
            memOffs += 2;
        if (postDecrement)
            memOffs -= 2;
    }

    /**
     * Writes a <code>int</code> into memory at current offset. Method setOffset()
     * should be called prior calling this method to setup the offset pointer.<br>
     * Offset pointer will be modified by 4 if post-increment is enabled or -4 if
     * post-decrement is enabled.
     *
     * @param value  a integer value (32 bit) that will be written into memory.
     * @exception RegionAddressOutOfBounds is thrown when trying to access data out of bounds
     *      of this memory region.
     */
    public void writeInt(int value) throws RegionAddressOutOfBoundsException
    {
        if (regStart + memOffs < regStart || regStart + memOffs >= regEnd)
            throw new RegionAddressOutOfBoundsException();

        writeInt0(regStart + memOffs, value);
        if (postIncrement)
            memOffs += 4;
        if (postDecrement)
            memOffs -= 4;
    }

    /**
     * Writes <code>byte</code> array to the memory starting at the current offset.
     * Method setOffset() should be called prior calling this method to setup the offset pointer.<br>
     * The offset pointer will be modified by the number of bytes written if post-increment
     * or post-decrement flag is set.
     *
     * @param array a source byte array
     * @param start starting offset in the array
     * @param length number of bytes to write
     * @exception RegionAddressOutOfBoundsException is thrown when trying to access data out of bounds
     *      of this memory region.
     * @exception IndexOutOfBoundsException is thrown when trying to access array data that out of bounds
     *      of the input byte array.
     */
    public void writeBytes(byte[] array, int start, int length)
        throws RegionAddressOutOfBoundsException, IndexOutOfBoundsException
    {
        if (start + length > array.length)
            throw new IndexOutOfBoundsException();
        if (regStart + memOffs < regStart || regStart + memOffs + length >= regEnd)
            throw new RegionAddressOutOfBoundsException();

        writeBytes0(regStart + memOffs, array, start, length);
        if (postIncrement)
            memOffs += length;
        if (postDecrement)
            memOffs -= length;
    }

    /**
     * Verifies if the requested meory area is valid flash memory area.
     *
     * @param start starting address of a new memory region.
     * @param length length of a new memory region.
     * @return true if memory region validity test passes, otherwise false is returned.
     */
    protected boolean regionOk(int start, int length)
    {
        if (!super.regionOk(start, length))
            return false;

        return regionOk0(start, length);
    }

    /**
     * Verifies if the requested area is valid flash memory region.
     * @param start starting address of a new memory region.
     * @param length length of a new memory region.
     * @return true if memory region validity test passes, otherwise false is returned.
     */
    protected static native boolean regionOk0(int start, int length);

    /**
     * Erases the specified sector in the flash memory chip.
     * @param sectorNo number of a sector to erase. If the used flash chip has eight
     *      sectors then acceptable values are 1 to 8.
     * @return true if flash sector was erased successfully, otherwise if the erase failed
     *      or invalid sector number was supplied false is returned.
     */
    public static native boolean eraseSector(int sectorNo);

    /*
     * Native methods that write 8, 16 and 32 bit values into memory.
     */
    protected static native boolean writeByte0(int Address, int Value);
    protected static native boolean writeShort0(int Address, int Value);
    protected static native boolean writeInt0(int Address, int Value);
    protected static native boolean writeBytes0(int Address, byte[] Src, int Start, int length);
}

